<script>
import {basicSetup} from 'codemirror'
import {EditorView,keymap, lineNumbers, highlightActiveLine} from '@codemirror/view'
import {defaultKeymap, history, historyKeymap} from '@codemirror/commands';
import {EditorState} from '@codemirror/state';
import {indentOnInput} from '@codemirror/language';
import { javascript } from '@codemirror/lang-javascript'
import { oneDark} from '@codemirror/theme-one-dark';
import {autocompletion} from '@codemirror/autocomplete';
import {foldGutter} from '@codemirror/language'
import { defineComponent, onMounted, ref, watch } from 'vue'

export default defineComponent({
  props: {
    modelValue: {
      type: String,
      default: '',
    },
  },
  setup(props, { emit }) {
    const editorView = ref();

    const updateValue =  EditorView.updateListener.of(v => {
      if (v.docChanged) {
        const newValue = v.state.doc.toString();
        emit('update:modelValue', newValue);
      }
    })

    onMounted(() => {
      const state = EditorState.create({
        extensions: [basicSetup,javascript(),
        updateValue, oneDark,keymap.of([...defaultKeymap, ...historyKeymap]),
          lineNumbers(), highlightActiveLine(), history(),
          indentOnInput(), autocompletion(), foldGutter(),
          EditorState.allowMultipleSelections.of(true)
        ],
      });
      editorView.value = new EditorView({
        doc: props.modelValue,
        state: state,parent: document.querySelector('#container')
      });

      watch(
        () => props.modelValue,
        newValue => {
          if (editorView.value) {
            const currentValue = editorView.value.state.doc.toString();
            if (newValue !== currentValue) {
              const transaction = editorView.value.state.update({
                changes: { from: 0, to: currentValue.length, insert: newValue }
              });
              editorView.value.dispatch(transaction);
            }
          }
        },
      )
    })
  },
})
</script>

<template>
  <div id="container">
  </div>
</template>

<style>
#container {
  width: 500px;
  height: 300px;
  position: absolute;
}
#container .cm-editor {
  height: 100%;
  width: 100%;
}
</style>
